package demoMod.stsconsole.commands;

import demoMod.stsconsole.ConsoleEntry;
import demoMod.stsconsole.dungeons.AbstractDungeon;
import demoMod.stsconsole.enums.ErrType;
import demoMod.stsconsole.helpers.LocalizedStrings;
import demoMod.stsconsole.interfaces.PurchaseSubscriber;
import demoMod.stsconsole.interfaces.Saleable;
import demoMod.stsconsole.rooms.ShopRoom;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Scanner;

public class Buy extends AbstractCommand {
    @Override
    public void execute(String[] args, Scanner sc) {
        if (!(AbstractDungeon.currDungeon.currMapNode.room instanceof ShopRoom)) {
            this.errMsg(ErrType.COMMAND_NOT_AVAILABLE);
            return;
        }
        if (args.length == 0) {
            this.errMsg(ErrType.WRONG_ARGUMENT);
            return;
        }
        List<String> cmdStrings = LocalizedStrings.getCommandStrings("Buy");
        ShopRoom.Shop shop = ShopRoom.currShop;
        if (args.length == 1) {
            switch (args[0]) {
                case "cardRemovalService":
                    if (canPurchase(shop.cardPurgeService)) {
                        AbstractDungeon.player.loseGold(shop.cardPurgeService.getPrice());
                        shop.cardPurgeService.purchase();
                        System.out.println(cmdStrings.get(2) + AbstractDungeon.player.getGold());
                        ConsoleEntry.triggerSubscribers(PurchaseSubscriber.class, "afterPurchase", new Class[]{Saleable.class, int.class}, new Object[]{shop.cardPurgeService, shop.cardPurgeService.getPrice()});
                    } else {
                        System.out.println(cmdStrings.get(0));
                    }
                    break;
                default:
                    this.errMsg(ErrType.WRONG_ARGUMENT);
            }
            return;
        }
        try {
            switch (args[0]) {
                case "coloredCard":
                    int index = Integer.parseInt(args[1]);
                    if (index >= shop.coloredCards.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    if (shop.coloredCards.get(index) == null) {
                        System.out.println(cmdStrings.get(1));
                        return;
                    }
                    if (canPurchase(shop.coloredCards.get(index))) {
                        AbstractDungeon.player.loseGold(shop.coloredCards.get(index).getPrice());
                        shop.coloredCards.get(index).purchase();
                        System.out.println(cmdStrings.get(2) + AbstractDungeon.player.getGold());
                        ConsoleEntry.subscribers.add(ShopRoom.defaultPurchaseLogic);
                        ConsoleEntry.triggerSubscribers(PurchaseSubscriber.class, "afterPurchase", new Class[]{Saleable.class, int.class}, new Object[]{shop.coloredCards.get(index), shop.coloredCards.get(index).getPrice()});
                        ConsoleEntry.subscribers.remove(ShopRoom.defaultPurchaseLogic);
                    } else {
                        System.out.println(cmdStrings.get(0));
                    }
                    break;
                case "colorlessCard":
                    index = Integer.parseInt(args[1]);
                    if (index >= shop.colorlessCards.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    if (shop.colorlessCards.get(index) == null) {
                        System.out.println(cmdStrings.get(1));
                        return;
                    }
                    if (canPurchase(shop.colorlessCards.get(index))) {
                        AbstractDungeon.player.loseGold(shop.colorlessCards.get(index).getPrice());
                        shop.colorlessCards.get(index).purchase();
                        System.out.println(cmdStrings.get(2) + AbstractDungeon.player.getGold());
                        ConsoleEntry.subscribers.add(ShopRoom.defaultPurchaseLogic);
                        ConsoleEntry.triggerSubscribers(PurchaseSubscriber.class, "afterPurchase", new Class[]{Saleable.class, int.class}, new Object[]{shop.colorlessCards.get(index), shop.colorlessCards.get(index).getPrice()});
                        ConsoleEntry.subscribers.remove(ShopRoom.defaultPurchaseLogic);
                    } else {
                        System.out.println(cmdStrings.get(0));
                    }
                    break;
                case "relic":
                    index = Integer.parseInt(args[1]);
                    if (index >= shop.relics.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    if (shop.relics.get(index) == null) {
                        System.out.println(cmdStrings.get(1));
                        return;
                    }
                    if (canPurchase(shop.relics.get(index))) {
                        AbstractDungeon.player.loseGold(shop.relics.get(index).getPrice());
                        shop.relics.get(index).purchase();
                        System.out.println(cmdStrings.get(2) + AbstractDungeon.player.getGold());
                        ConsoleEntry.subscribers.add(ShopRoom.defaultPurchaseLogic);
                        ConsoleEntry.triggerSubscribers(PurchaseSubscriber.class, "afterPurchase", new Class[]{Saleable.class, int.class}, new Object[]{shop.relics.get(index), shop.relics.get(index).getPrice()});
                        ConsoleEntry.subscribers.remove(ShopRoom.defaultPurchaseLogic);
                    } else {
                        System.out.println(cmdStrings.get(0));
                    }
                    break;
                case "potion":
                    index = Integer.parseInt(args[1]);
                    if (index >= shop.potions.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    if (shop.potions.get(index) == null) {
                        System.out.println(cmdStrings.get(1));
                        return;
                    }
                    if (canPurchase(shop.potions.get(index))) {
                        AbstractDungeon.player.loseGold(shop.potions.get(index).getPrice());
                        shop.potions.get(index).purchase();
                        System.out.println(cmdStrings.get(2) + AbstractDungeon.player.getGold());
                        ConsoleEntry.subscribers.add(ShopRoom.defaultPurchaseLogic);
                        ConsoleEntry.triggerSubscribers(PurchaseSubscriber.class, "afterPurchase", new Class[]{Saleable.class, int.class}, new Object[]{shop.potions.get(index), shop.potions.get(index).getPrice()});
                        ConsoleEntry.subscribers.remove(ShopRoom.defaultPurchaseLogic);
                    } else {
                        System.out.println(cmdStrings.get(0));
                    }
                    break;
            }
        } catch (NumberFormatException e) {
            this.errMsg(ErrType.WRONG_ARGUMENT);
        }
    }

    private boolean canPurchase(Saleable saleable) {
        boolean[] result = new boolean[] {true};
        ConsoleEntry.subscribers.add(ShopRoom.defaultPurchaseLogic);
        ConsoleEntry.triggerSubscribers(
                PurchaseSubscriber.class,
                "canPurchase",
                new Class[]{Saleable.class, int.class},
                new Object[]{saleable, saleable.getPrice()},
                (method, params, subscriber) -> {
                    try {
                        result[0] = result[0] && (boolean) method.invoke(subscriber, params);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
        );
        ConsoleEntry.subscribers.remove(ShopRoom.defaultPurchaseLogic);
        return result[0];
    }

    @Override
    public boolean requiredPrompt(String currentPrompt) {
        return currentPrompt.contains("Dungeon");
    }
}
